#!/usr/bin/python
# coding=utf-8
from selenium.webdriver.common.by import By
from chrome import ChromeWebDriver
from bs4 import BeautifulSoup
import re, json, random, time
from urllib import parse
from job_categories import JobCategories

_USE_DEBUG = 0

class BossZhiPin:
    def __init__(self, job_title=None, city: str = '上海'):
        if job_title is None:
            job_title = JobCategories.GetCategories('单片机')

        self.driver = ChromeWebDriver()

        # name state list
        self.job_info = {}
        for job in job_title:
            if job not in self.job_info:
                self.job_info.update({job: {'city': city, 'state': 0, 'work': []}})

        if _USE_DEBUG == 0:
            self.city_fresh()
            time.sleep(8)

            # url = 'https://login.zhipin.com/login'
            # self.driver.get_url(url)
            # self.driver.implicitly_wait(10)
            # input('请输入回车确认是否已经登录')
            self.traverse_jobs()

        else:
            url = 'file:///C:/Users/a8777/Desktop/test.mhtml'
            self.traverse_page(url=url, city_name=city, job_name=job_title[0], deep=1)

        # 退出
        self.driver.quit()

    def traverse_jobs(self):
        while True:
            cnt = 0
            temp = []
            for name in self.job_info.keys():
                temp.append(name)

            for name in temp:
                info = self.job_info[name]
                if info['state'] == 0:
                    self.traverse_page(job_name=name, city_name=info['city'])
                    cnt += 1
                else:
                    cnt += 1

            if cnt == len(self.job_info):
                break

    @staticmethod
    def get_associate_job(associate_list: list, soup: BeautifulSoup):
        recommend_list = soup.select('.related-search-list li')
        # link_list = link_list.find_all('')

        for job in recommend_list:
            if job.text not in associate_list:
                associate_list.append(job.text)

    def traverse_page(self, job_name: str, city_name: str, url: str = '', deep: int = -1):
        def _has_next_page(soup):
            try:
                html_page_opt = soup.find('div', class_='options-pages')
                html_page_opt = html_page_opt.find_all('a')[-1]
            except:
                print(soup.prettify())
                print('html_page_opt error')
                exit(-1)

            if html_page_opt is not None and 'class' in html_page_opt.attrs:
                status = html_page_opt.attrs['class']
                # print(status)
                if isinstance(status, list) and len(status):
                    status = status[-1]

                if isinstance(status, str) and status == 'disabled':
                    return 0
                return 1
            return 0

        def _switch_next_page(driver):
            # a = self.driver.find_element(By.CLASS_NAME, 'ui-icon-arrow-right')
            links = driver.find_elements(By.XPATH, '//div[@class="options-pages"]//a')

            if len(links):
                links = links[-1]
                # print(links.get_attribute("href"), links.get_attribute("href"))
                try:
                    links.click()
                except:
                    print(links.text)
                    print(BeautifulSoup(driver.page_source, 'lxml').prettify())
                    exit(-1)
                time.sleep(8)
                return 0

            return -1

        job_info = []
        job_associate = []

        if len(url) == 0:
            url = self.create_url(job=job_name, city=city_name)

        self.driver.get_url(url, 10)
        time.sleep(8)

        while True:
            self.soup = BeautifulSoup(self.driver.page_source, 'lxml')
            print(f'job:{job_name}, city:{city_name}, url:{self.driver.current_url}')

            if _USE_DEBUG:
                print(self.soup.prettify())

            self.update_work_info(job_info, self.soup)

            # # 关联相关职业
            # if associate:
            #     self.get_associate_job(job_associate, self.soup)

            # 指定遍历次数处理
            if deep > 0:
                deep -= 1

            if deep == 0:
                break

            # 查找下一页按钮
            if _has_next_page(self.soup):
                if _switch_next_page(self.driver) == -1:
                    print('switch next page failed, exit')
            else:
                # print('Find Dond, Exit')
                break

        # JOB List处理
        if job_name in self.job_info:
            self.job_info[job_name]['work'] += job_info
        else:
            self.job_info.update({job_name: {'city': city_name, 'state': 1, 'associate': False, 'work': job_info}})

        # 推荐岗位处理
        for job in job_associate:
            if job not in self.job_info:
                self.job_info.update({job: {'city': city_name, 'state': 0, 'associate': False, 'work': []}})

        return job_info, job_associate

    def create_url(self, job: str, city: str = '上海'):
        # 找不到城市切换成全国站
        if city in self.city_dict:
            city_code = self.city_dict[city]
        else:
            city_code = 100010000
        url = f'https://www.zhipin.com/web/geek/job?city={city_code}&query={self.cn2urlcode(job)}'
        return url

    def city_fresh(self):
        url = 'https://www.zhipin.com/wapi/zpCommon/data/city.json'
        self.driver.get_url(url)
        self.soup = BeautifulSoup(self.driver.page_source, 'lxml')
        # print(self.soup.prettify())

        element = self.soup.find('body')
        city_dict = json.loads(element.text)

        self.city_dict = {}
        self.current_city = []
        municipality = ['北京', '上海', '天津', '重庆']
        if city_dict['message'] == 'Success':
            province_list = city_dict['zpData']['cityList']
            local_city = city_dict['zpData']['locationCity']

            for province in province_list:
                city_list = province['subLevelModelList']
                for city in city_list:
                    self.city_dict.update({city['name']: city['code']})
                    # print(city['name'], city['code'])

            self.local_city = {local_city['name']: local_city['code']}

        print(self.local_city)

    @staticmethod
    def cn2urlcode(ch_str: str, encoding: str = 'utf-8'):
        return parse.quote(ch_str.encode(encoding=encoding))

    @staticmethod
    def get_city_info(soup: BeautifulSoup):
        city_dict = {}
        current_city = ''

        html_city_list = soup.find('ul', class_='dropdown-city-list')

        for city in html_city_list:
            if 'ka' in city.attrs:
                city_code = str(city.attrs['ka']).replace('sel-city-', '')
                city_dict.update({city.text: city_code})

            if 'class' in city.attrs and len(city.attrs['class']):
                current_city = city.text

        # print(f'city list:{city_dict}, current city:{current_city}')
        return current_city, city_dict

    @staticmethod
    def update_work_info(work_list, soup: BeautifulSoup):
        def _get_job_name(work):
            return {'岗位': work.select('.job-name')[0].text}

        def _get_job_salary(work):
            return {'薪酬': work.select('.salary')[0].text}

        def _get_job_area(work):
            return {'工作地点': BossZhiPinParser.text_split(work.select('.job-area')[0].text)}

        def _get_job_url(work):
            html_job_url = work.find('a', class_='job-card-left')

            if html_job_url is not None and 'href' in html_job_url.attrs:
                company_url = 'https://www.zhipin.com' + html_job_url.attrs['href']
            else:
                company_url = ''

            return {'岗位链接': company_url}

        def _get_job_info(work):
            def _job_salary_list(salary: str):
                salary_list = re.findall(r'\d+\.?\d*', salary)
                if len(salary_list) == 1:
                    salary_list = [int(salary_list[0])]
                elif len(salary_list):
                    salary_list = [int(val) for val in salary_list]
                else:
                    salary_list = []

                return salary_list

            info = {'岗位': work.select('.job-name')[0].text,
                    '薪酬': _job_salary_list(str(work.select('.salary')[0].text)),
                    '薪酬描述': str(work.select('.salary')[0].text),
                    '工作地点': BossZhiPinParser.text_split(work.select('.job-area')[0].text)}

            tag_list = []
            company_tags = work.find_all('ul', class_='tag-list')[0]
            company_tags = company_tags.find_all('li')
            for tag in company_tags:
                tag_value = BossZhiPinParser.text_split(tag.text)
                tag_list += tag_value
                # print(tag_value)

            info.update({'岗位Tag': tag_list})

            return info

        def _get_company_name(work):
            return {'公司名称': BossZhiPinParser.text_split(work.select('.company-name')[0].text)}

        def _get_company_spec(work):
            return {'公司特点': BossZhiPinParser.text_split(work.select('.info-desc')[0].text)}

        def _get_company_url(work):
            company_name = work.select('.company-name')[0]
            company_url = company_name.find('a')

            if 'href' in company_url.attrs:
                company_url = 'https://www.zhipin.com' + company_url.attrs['href']
            else:
                company_url = ''

            return {'公司链接': company_url}

        def _get_company_tag(work):
            tag_list = []
            company_tags = work.find_all('ul', class_='company-tag-list')[0]
            company_tags = company_tags.find_all('li')
            for tag in company_tags:
                tag_value = BossZhiPinParser.text_split(tag.text)
                tag_list += tag_value
                # print(tag_value)

            return {'公司Tag': tag_list}

        def _get_company_info(work):
            info = {'公司名称': BossZhiPinParser.text_split(work.select('.company-name')[0].text),
                    '公司特点': BossZhiPinParser.text_split(work.select('.info-desc')[0].text)}

            tag_list = []
            company_tags = work.find_all('ul', class_='company-tag-list')[0]
            company_tags = company_tags.find_all('li')
            for tag in company_tags:
                tag_value = BossZhiPinParser.text_split(tag.text)
                tag_list += tag_value
                # print(tag_value)

            info.update({'公司Tag': tag_list})
            info.update({'工作地点': BossZhiPinParser.text_split(work.select('.job-area')[0].text)})

            return info

        def _get_company_hr(work):
            html_info = work.find_all('div', class_='info-public')[0]
            hr_name = str(html_info.text)
            hr_part = str(html_info.find('em').text)

            info = {'HR': [hr_name.replace(hr_part, ''), hr_part]}
            return info

        html_func_list = [_get_job_info, _get_company_info, _get_company_hr,
                          _get_job_url, _get_company_url]
        html_work_list = soup.select('.job-list-box .job-card-wrapper')
        for index, work in enumerate(html_work_list):
            # print(work.prettify())

            info = {'序号': len(work_list) + 1}
            for func in html_func_list:
                info.update(func(work))

            print(info)
            work_list.append(info)

        # print(html_work_list)

        return work_list

    def put_info(self):
        # for item in self.job_info:
        #     print(item)
        pass

    @staticmethod
    def text_split(in_text):
        text_list = []
        key_list = [';', '\n', ' ', '\\', '/', '·']
        reg_str = str(in_text)

        for i in key_list:
            reg_str = reg_str.replace(i, '\n')

        for text in reg_str.split('\n'):
            if len(text) and text != '\n':
                text_list.append(text)
        return text_list

    def __del__(self):
        self.driver.quit()
        del self.driver

    # @staticmethod
    # def get_company_url(job):
    #     temp = ['HR']
    #     desc = str(job.find_element(By.CSS_SELECTOR, '.info-public').text)
    #     department = str(job.find_element(By.CSS_SELECTOR, '.info-public em').text)
    #     desc_list = [desc.replace(department, ''), department]
    #     return {temp[0]: desc_list}
